package com.semanticweb.webapp.model.ontology;

import org.apache.lucene.document.Document;

import com.semanticweb.project.search.api.AbstractDocument;
import com.semanticweb.webapp.model.ontology.Dimension.Type;
import com.semanticweb.webapp.ontology.CIDOC;
import com.semanticweb.webapp.ontology.Ont;
import com.semanticweb.webapp.search.SearchMD;

public class Item implements IEntity, AbstractDocument {

    private final String id;
    private Author author;
    private Category category;
    private Collection collection;
    private Condition condition;
    private Count count;
    private CreationDate creationDate;
    private CreationPlace creationPlace;
    private Description description;
    private Dimension width;
    private Dimension height;
    private Dimension radius;
    private Dimension weight;
    private Dimension thickness;
    private Dimension length;
    private History history;
    private InventaryNumber inventaryNumber;
    private Literature literature;
    private MaterialAndTechnique materialAndTechnique;
    private Museum museum;
    private NegativeLabelAndNumber negativeLabelAndNumber;
    private NumberInDocumentation numberInDocumentation;
    private NumberInEntranceBook numberInEntranceBook;
    private Photography photography;
    private Price price;
    private ProcurementType procurementType;
    private Remark remark;
    private Repository repository;
    private Restoration restoration;
    private StylePeriod stylePeriod;
    private Subject subject;
    private SubjectProcessedBy subjectProcessedBy;

    public Item() {
        this.id = System.currentTimeMillis() + "";
        initialize(this.id);
    }

    public Item(final String id) {
        this.id = InventaryNumber.findID(id);
        if (this.id == null) {
            throw new IllegalArgumentException(String.format("Item with id [%s] does not exsist.", id));
        }
        initialize(this.id);
    }

    private void initialize(final String id) {
        this.author = new Author(id);
        this.category = new Category(id);
        this.collection = new Collection(id);
        this.condition = new Condition(id);
        this.count = new Count(id);
        this.creationDate = new CreationDate(id);
        this.creationPlace = new CreationPlace(id);
        this.description = new Description(id);
        this.width = new Dimension(id, Type.WIDTH);
        this.height = new Dimension(id, Type.HEIGHT);
        this.radius = new Dimension(id, Type.RADIUS);
        this.weight = new Dimension(id, Type.WEIGHT);
        this.thickness = new Dimension(id, Type.THICKNESS);
        this.length = new Dimension(id, Type.LENGTH);
        this.history = new History(id);
        this.inventaryNumber = new InventaryNumber(id);
        this.literature = new Literature(id);
        this.materialAndTechnique = new MaterialAndTechnique(id);
        this.museum = new Museum(id);
        this.negativeLabelAndNumber = new NegativeLabelAndNumber(id);
        this.numberInDocumentation = new NumberInDocumentation(id);
        this.numberInEntranceBook = new NumberInEntranceBook(id);
        this.photography = new Photography(id);
        this.price = new Price(id);
        this.procurementType = new ProcurementType(id);
        this.remark = new Remark(id);
        this.repository = new Repository(id);
        this.restoration = new Restoration(id);
        this.stylePeriod = new StylePeriod(id);
        this.subject = new Subject(id);
        this.subjectProcessedBy = new SubjectProcessedBy(id);
    }

    public Author getAuthor() {
        return this.author;
    }

    public Category getCategory() {
        return this.category;
    }

    public Collection getCollection() {
        return this.collection;
    }

    public Condition getCondition() {
        return this.condition;
    }

    public Count getCount() {
        return this.count;
    }

    public CreationDate getCreationDate() {
        return this.creationDate;
    }

    public CreationPlace getCreationPlace() {
        return this.creationPlace;
    }

    public Description getDescription() {
        return this.description;
    }

    public Dimension getWidth() {
        return this.width;
    }

    public Dimension getHeight() {
        return this.height;
    }

    public Dimension getRadius() {
        return this.radius;
    }

    public Dimension getWeight() {
        return this.weight;
    }

    public Dimension getThickness() {
        return this.thickness;
    }

    public Dimension getLength() {
        return this.length;
    }

    public History getHistory() {
        return this.history;
    }

    public InventaryNumber getInventaryNumber() {
        return this.inventaryNumber;
    }

    public Literature getLiterature() {
        return this.literature;
    }

    public MaterialAndTechnique getMaterialAndTechnique() {
        return this.materialAndTechnique;
    }

    public Museum getMuseum() {
        return this.museum;
    }

    public NegativeLabelAndNumber getNegativeLabelAndNumber() {
        return this.negativeLabelAndNumber;
    }

    public NumberInDocumentation getNumberInDocumentation() {
        return this.numberInDocumentation;
    }

    public NumberInEntranceBook getNumberInEntranceBook() {
        return this.numberInEntranceBook;
    }

    public Photography getPhotography() {
        return this.photography;
    }

    public Price getPrice() {
        return this.price;
    }

    public ProcurementType getProcurementType() {
        return this.procurementType;
    }

    public Remark getRemark() {
        return this.remark;
    }

    public Repository getRepository() {
        return this.repository;
    }

    public Restoration getRestoration() {
        return this.restoration;
    }

    public StylePeriod getStylePeriod() {
        return this.stylePeriod;
    }

    public Subject getSubject() {
        return this.subject;
    }

    public SubjectProcessedBy getSubjectProcessedBy() {
        return this.subjectProcessedBy;
    }

    public String getId() {
        return this.id;
    }

    public static String formatItemURI(final String id) {
        return Ont.formatURI(id);
    }

    public static String formatItemQueryURI(final String id) {
        return Ont.formatQueryURI(id);
    }

    @Override
    public void toRDF() {
        if (this.inventaryNumber.getValue() == null || this.inventaryNumber.getValue().isEmpty()) {
            throw new IllegalArgumentException("Inventary number can't be null or empty");
        }
        if (InventaryNumber.inventaryNumberExists(this.inventaryNumber.getValue())) {
            throw new IllegalArgumentException("Inventary number already exists: " + this.inventaryNumber.getValue());
        }

        Ont.getOntology().createIndividual(CIDOC.E22.getFullValue(), Ont.formatURI(this.id));
        this.author.toRDF();
        this.category.toRDF();
        this.collection.toRDF();
        this.condition.toRDF();
        this.count.toRDF();
        this.creationDate.toRDF();
        this.creationPlace.toRDF();
        this.description.toRDF();
        this.height.toRDF();
        this.history.toRDF();
        this.length.toRDF();
        this.inventaryNumber.toRDF();
        this.literature.toRDF();
        this.materialAndTechnique.toRDF();
        this.museum.toRDF();
        this.negativeLabelAndNumber.toRDF();
        this.numberInDocumentation.toRDF();
        this.numberInEntranceBook.toRDF();
        this.photography.toRDF();
        this.price.toRDF();
        this.procurementType.toRDF();
        this.radius.toRDF();
        this.remark.toRDF();
        this.repository.toRDF();
        this.restoration.toRDF();
        this.stylePeriod.toRDF();
        this.subject.toRDF();
        this.subjectProcessedBy.toRDF();
        this.thickness.toRDF();
        this.weight.toRDF();
        this.width.toRDF();
    }

    public void fromRDF() {
        this.author.fromRDF();
        this.category.fromRDF();
        this.collection.fromRDF();
        this.condition.fromRDF();
        this.count.fromRDF();
        this.creationDate.fromRDF();
        this.creationPlace.fromRDF();
        this.description.fromRDF();
        this.height.fromRDF();
        this.history.fromRDF();
        this.length.fromRDF();
        this.inventaryNumber.fromRDF();
        this.literature.fromRDF();
        this.materialAndTechnique.fromRDF();
        this.museum.fromRDF();
        this.negativeLabelAndNumber.fromRDF();
        this.numberInDocumentation.fromRDF();
        this.numberInEntranceBook.fromRDF();
        this.photography.fromRDF();
        this.price.fromRDF();
        this.procurementType.fromRDF();
        this.radius.fromRDF();
        this.remark.fromRDF();
        this.repository.fromRDF();
        this.restoration.fromRDF();
        this.stylePeriod.fromRDF();
        this.subject.fromRDF();
        this.subjectProcessedBy.fromRDF();
        this.thickness.fromRDF();
        this.weight.fromRDF();
        this.width.fromRDF();
    }

    @Override
    public Document generateDocument() {
        final Document doc = new Document();

        this.author.toIndexDocument(doc);
        this.category.toIndexDocument(doc);
        this.collection.toIndexDocument(doc);
        this.condition.toIndexDocument(doc);
        this.count.toIndexDocument(doc);
        this.creationDate.toIndexDocument(doc);
        this.creationPlace.toIndexDocument(doc);
        this.description.toIndexDocument(doc);
        this.width.toIndexDocument(doc);
        this.height.toIndexDocument(doc);
        this.radius.toIndexDocument(doc);
        this.weight.toIndexDocument(doc);
        this.thickness.toIndexDocument(doc);
        this.length.toIndexDocument(doc);
        this.history.toIndexDocument(doc);
        this.inventaryNumber.toIndexDocument(doc);
        this.literature.toIndexDocument(doc);
        this.materialAndTechnique.toIndexDocument(doc);
        this.museum.toIndexDocument(doc);
        this.negativeLabelAndNumber.toIndexDocument(doc);
        this.numberInDocumentation.toIndexDocument(doc);
        this.numberInEntranceBook.toIndexDocument(doc);
        this.photography.toIndexDocument(doc);
        this.price.toIndexDocument(doc);
        this.procurementType.toIndexDocument(doc);
        this.remark.toIndexDocument(doc);
        this.repository.toIndexDocument(doc);
        this.restoration.toIndexDocument(doc);
        this.stylePeriod.toIndexDocument(doc);
        this.subject.toIndexDocument(doc);
        this.subjectProcessedBy.toIndexDocument(doc);

        return doc;
    }

    @Override
    public String defaultField() {
        return SearchMD.CONTENT.getKey();
    }
}